package org.jeecg.modules.wlhy.bill.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.paycenter.channel.bankdocking.service.NhBankService;
import org.jeecg.modules.paycenter.pay.dto.PayBillData;
import org.jeecg.modules.wlhy.bill.entity.HyDriverBill;
import org.jeecg.modules.wlhy.bill.entity.HyShippingNoteBill;
import org.jeecg.modules.wlhy.bill.entity.ImportShippingBillDTO;
import org.jeecg.modules.wlhy.bill.mapper.HyShippingNoteBillMapper;
import org.jeecg.modules.wlhy.bill.service.IHyDriverBillService;
import org.jeecg.modules.wlhy.bill.service.IHyShippingNoteBillService;
import org.jeecg.modules.wlhy.company.entity.HyCompany;
import org.jeecg.modules.wlhy.company.service.IHyCompanyService;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriver;
import org.jeecg.modules.wlhy.hydriver.service.impl.HyDriverServiceImpl;
import org.jeecg.modules.wlhy.hyevent.event.PicDownloadEvent;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicle;
import org.jeecg.modules.wlhy.hyvehicle.service.impl.HyVehicleServiceImpl;
import org.jeecg.modules.wlhy.shipping.entity.HyShippingNote;
import org.jeecg.modules.wlhy.shipping.service.IHyShippingNoteService;
import org.jeecg.modules.wlhy.utils.CodeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: hy_shipping_note_bill
 * @Author: jeecg-boot
 * @Date:   2021-01-20
 * @Version: V1.0
 */
@Service
@Slf4j
//@EnableAsync
public class HyShippingNoteBillServiceImpl extends ServiceImpl<HyShippingNoteBillMapper, HyShippingNoteBill> implements IHyShippingNoteBillService {

    //银行文件路径
    @Value(value = "${jeecg.path.bank}")
    private String bankPath;

    @Resource
    private IHyShippingNoteService shippingNoteService;

    @Autowired
    private NhBankService nhBankService;

    @Autowired
    private CodeUtil codeUtil;

    @Autowired
    private IHyDriverBillService hyDriverBillService;

    @Autowired
    private IHyCompanyService companyService;

    @Autowired private HyDriverServiceImpl driverService;

    @Autowired private HyVehicleServiceImpl vehicleService;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public IPage<HyShippingNoteBill> getPageList(Page<HyShippingNoteBill> page,
                                                QueryWrapper<HyShippingNoteBill> queryWrapper) {
        IPage<HyShippingNoteBill> pageList = baseMapper.getPageList(page, queryWrapper);
        return pageList;
    }

    @Override
    public List<HyShippingNoteBill> getList(QueryWrapper<HyShippingNoteBill> queryWrapper) {
        return baseMapper.getList(queryWrapper);
    }


    @Override
    public String queryBankHd(HyShippingNoteBill hyShippingNoteBill){
        if (hyShippingNoteBill.getBankHd() != null){
            return hyShippingNoteBill.getBankHd();
        }

        if ("5".equals(hyShippingNoteBill.getPayChannel())) {
            throw new JeecgBootException("该运单线下支付不支持回单信息下载！");
        }

//        String shippingNoteId = hyShippingNoteBill.getShippingId();
//        HyShippingNote shippingNote = shippingNoteService.getById(shippingNoteId);
        //付款回单 查本方账号明细 金额带负号
        String filename = nhBankService.queryBankHd(hyShippingNoteBill.getPayDt(), hyShippingNoteBill.getDbProv(), hyShippingNoteBill.getDbaccno(),
                hyShippingNoteBill.getBillNum(), hyShippingNoteBill.getAmt().negate());
        if(filename != null){
            hyShippingNoteBill.setBankHd(filename);
            //todo hd
//            String bankHdImg = filename.substring(0, filename.lastIndexOf(".")) + ".jpg";
//            hyShippingNoteBill.setBankHdImg(bankHdImg);
            this.updateById(hyShippingNoteBill);
        }
        return filename;
    }


    @Override
    public List<HyShippingNoteBill> driverDeclareStat(Date startTime, Date endTime) {
        List <HyShippingNoteBill> shippingNoteBills =  baseMapper.driverDeclareStat(startTime,endTime);
        return CollectionUtils.isNotEmpty(shippingNoteBills) ? shippingNoteBills : new ArrayList <>();
    }

    @Override
    @Transactional
    public void saveCompanyBill(PayBillData payBillData) {
        HyShippingNoteBill shippingNoteBill = payBillData.getShippingNoteBill();
        HyDriverBill driverBill = payBillData.getDriverBill();
        this.updateById(shippingNoteBill);
        if (driverBill != null) {
            hyDriverBillService.updateById(driverBill);
        }
    }


    /**
     * 导入运单资金流水
     * @param listShippingBill
     */
    @Override
    @Transactional
    public void saveBatchShippingNote(List<HyShippingNoteBill> listShippingBill){
        if(CollectionUtils.isNotEmpty(listShippingBill)) {
            this.saveBatch(listShippingBill);
        }
    }

    @Override
    public List <ImportShippingBillDTO> queryImportShippingBillDTOS(List <ImportShippingBillDTO> listShippingBill) {
        //查询公司
        List<String> companyNames =   listShippingBill.stream().map(
                item -> item.getCompanyName().trim()
        ).distinct().filter(Objects::nonNull).collect(Collectors.toList());
        QueryWrapper queryWrapperCompanyName = new QueryWrapper();
        queryWrapperCompanyName.in("company_name"  ,companyNames);
        List<HyCompany>  companyNameList = companyService.list(queryWrapperCompanyName);

        if(companyNameList.size() != companyNames.size()){
            List<String>  dbCompanyNames = companyNameList.stream().map(
                    item -> item.getCompanyName()
            ).collect(Collectors.toList());

            String filterCompanyNames = companyNames.stream()
                    .filter(item -> !dbCompanyNames.contains(item))
                    .collect(Collectors.joining(",", "(", ")"));
            throw new JeecgBootException(filterCompanyNames+ "公司数据信息有误");
        }

        Map <String ,String> companyNameMaps =  companyNameList.stream().collect(
                Collectors.toMap(HyCompany::getCompanyName, HyCompany::getId,  (key1, key2) -> key2));


        //运单
        List<String> shippingNoteNumbers =   listShippingBill.stream().map(
                item ->item.getShippingNoteNumber().trim()
        ).distinct().filter(Objects::nonNull).collect(Collectors.toList());


        int sections = 10;
        List<HyShippingNote>  shippingNoteList = new LinkedList <>() ;
        for (int index = 0, end = 0; index < shippingNoteNumbers.size(); index = end) {
            end = (end + sections) <= shippingNoteNumbers.size() ? end + sections : shippingNoteNumbers.size();
            if (index < end) {
                QueryWrapper <HyShippingNote> queryWrappershipping = new QueryWrapper();
                queryWrappershipping.in("shipping_note_number" ,shippingNoteNumbers.subList(index, end));
                shippingNoteList.addAll(shippingNoteService.list(queryWrappershipping));
            }
        }


        if(shippingNoteNumbers.size() != shippingNoteList.size()){
            List<String>  dbShippingNoteNumbers = shippingNoteList.stream().map(
                    item -> item.getShippingNoteNumber()
            ).collect(Collectors.toList());

            String filterShippingNoteNumbers = shippingNoteNumbers.stream()
                    .filter(item -> !dbShippingNoteNumbers.contains(item))
                    .collect(Collectors.joining(",", "(", ")"));
            throw new JeecgBootException(filterShippingNoteNumbers+ "运单数据信息有误");

        }

        Map<String , HyShippingNote> shippingNoteMaps =  shippingNoteList.stream().collect(
                Collectors.toMap(HyShippingNote::getShippingNoteNumber, Function.identity(),  (key1, key2) -> key2));


        //查询司机
//        List<String> idcards =   listShippingBill.stream().map(
//                item ->item.getActualCarrierId().trim()
//        ).distinct().filter(Objects::nonNull).collect(Collectors.toList());
//
//        int section = 10;
//        List<HyDriver> driverList = new LinkedList <>() ;
//        for (int index = 0, end = 0; index < idcards.size(); index = end) {
//            end = (end + section) <= idcards.size() ? end + section : idcards.size();
//            if (index < end) {
//                QueryWrapper <HyDriver> querydriverWrapper = new QueryWrapper();
//                querydriverWrapper.in("idcard" ,idcards.subList(index, end));
//                driverList.addAll(driverService.list(querydriverWrapper));
//            }
//        }
//
//        if(idcards.size() != driverList.size()){
//            List<String>  dbIdcards = driverList.stream().map(
//                    item -> item.getIdcard()
//            ).collect(Collectors.toList());
//
//            String filterIdcards = idcards.stream()
//                    .filter(item -> !dbIdcards.contains(item))
//                    .collect(Collectors.joining(",", "(", ")"));
//
//            throw new JeecgBootException(filterIdcards+"司机身份证号数据信息有误");
//        }
//
//        Map<String , HyDriver> idcardsMaps =  driverList.stream().collect(
//                Collectors.toMap(HyDriver::getIdcard, Function.identity(),  (key1, key2) -> key2));

        //查询车辆
        List<String> vehicleNumbers =   listShippingBill.stream().map(
                item ->item.getVehicleNumber().trim()
        ).distinct().filter(Objects::nonNull).collect(Collectors.toList());

        int sectionv = 10;
        List<HyVehicle> vehicleList  = new LinkedList <>() ;
        for (int index = 0, end = 0; index < vehicleNumbers.size(); index = end) {
            end = (end + sectionv) <= vehicleNumbers.size() ? end + sectionv : vehicleNumbers.size();
            if (index < end) {
                QueryWrapper <HyVehicle> queryWrapperVehicle = new QueryWrapper();
                queryWrapperVehicle.in("vehicle_number" ,vehicleNumbers.subList(index, end));
                vehicleList.addAll(vehicleService.list(queryWrapperVehicle));
            }
        }

        if(vehicleNumbers.size() != vehicleList.size()){
            List<String>  dbVehicleNumbers = vehicleList.stream().map(
                    item -> item.getVehicleNumber()
            ).collect(Collectors.toList());

            String filterVehicleNumbers = vehicleNumbers.stream()
                    .filter(item -> !dbVehicleNumbers.contains(item))
                    .collect(Collectors.joining(",", "(", ")"));
            throw new JeecgBootException(filterVehicleNumbers+"车辆数据信息有误");
        }


        Map<String , HyVehicle> vehicleNumMaps = vehicleList.stream().collect(
                Collectors.toMap(HyVehicle::getVehicleNumber, Function.identity(),  (key1, key2) -> key2));


        for (ImportShippingBillDTO importShippingBillDTO : listShippingBill) {
            importShippingBillDTO.setCompanyId(companyNameMaps.get(importShippingBillDTO.getCompanyName().trim()));

            importShippingBillDTO.setShippingId( shippingNoteMaps.get(importShippingBillDTO.getShippingNoteNumber().trim()).getId()  );

            importShippingBillDTO.setShippingNotes(shippingNoteMaps.get(importShippingBillDTO.getShippingNoteNumber().trim()) );

//            if(MapUtils.isNotEmpty(idcardsMaps) && idcardsMaps.get(importShippingBillDTO.getActualCarrierId().trim()) != null){
//                HyDriver driver = idcardsMaps.get(importShippingBillDTO.getActualCarrierId().trim());
//                importShippingBillDTO.setDriverId(driver.getId());
//                importShippingBillDTO.setCarrier(driver.getDriverName());
//                importShippingBillDTO.setActualCarrierId(driver.getIdcard());
//            }
            if(MapUtils.isNotEmpty(vehicleNumMaps) && vehicleNumMaps.get(importShippingBillDTO.getVehicleNumber().trim()) != null){
                HyVehicle vehicle = vehicleNumMaps.get(importShippingBillDTO.getVehicleNumber().trim());
                importShippingBillDTO.setVehicleId(vehicle.getId());
                importShippingBillDTO.setVehicleNumber(vehicle.getVehicleNumber());
                importShippingBillDTO.setVehicleColorCode(vehicle.getVehiclePlateColorCode());
            }
        }
        return  listShippingBill;
    }

    @Override
    public  HyShippingNoteBill ImportShippingBillDTOTOHyShippingNoteBill(
            ImportShippingBillDTO importShippingBillDTO ,String key ) {
        if (importShippingBillDTO == null) {
            throw new JeecgBootException("数据对象为空");
        }
        if(StringUtils.isBlank(importShippingBillDTO.getCompanyId())){
            throw new JeecgBootException("第"+ key+ "行 " + importShippingBillDTO.getCompanyName()+" 公司信息不能为空,请先补充信息");
        }
        if(StringUtils.isBlank(importShippingBillDTO.getBillNum())) {
            throw new JeecgBootException("第"+ key+ "行  流水号不能为空,请先补充信息");
        }
        if(StringUtils.isBlank(importShippingBillDTO.getShippingId())){
            throw new JeecgBootException("第"+ key+ "行 " + importShippingBillDTO.getShippingNoteNumber()+" 运单信息不能为空,请先补充信息");
        }
        HyShippingNote  hyShippingNote =  importShippingBillDTO.getShippingNotes();
        if(hyShippingNote == null){
            throw new JeecgBootException("第"+ key+ "行 " + importShippingBillDTO.getShippingNoteNumber()+"运单信息不能为空,请先补充信息");
        }
//        if(StringUtils.isBlank(importShippingBillDTO.getDriverId())){
//            throw new JeecgBootException("第"+ key+ "行 " + importShippingBillDTO.getCarrier()+" 司机名称不能为空,请先补充信息");
//        }
//        if(StringUtils.isBlank(importShippingBillDTO.getActualCarrierId())){
//            throw new JeecgBootException("第"+ key+ "行 司机身份证不能为空");
//        }
        if(StringUtils.isBlank(importShippingBillDTO.getVehicleId())){
            throw new JeecgBootException("第"+ key+ "行 " + importShippingBillDTO.getVehicleNumber() + " 车辆号码信息不能为空,请先补充信息");
        }
        if(StringUtils.isBlank(importShippingBillDTO.getVehicleColorCode())){
            throw new JeecgBootException("第"+ key+ "行车辆颜色信息不能为空");
        }

        if(importShippingBillDTO.getAmt() == null || importShippingBillDTO.getAmt().compareTo(BigDecimal.ZERO) ==0 ){
            throw new JeecgBootException("第"+ key+ "行金额不能为空");
        }

        if(StringUtils.isBlank(importShippingBillDTO.getCraccno())){
            throw new JeecgBootException("第"+ key+ "行司机银行卡号不能为空");
        }
        if(StringUtils.isBlank(importShippingBillDTO.getBankCode())){
            throw new JeecgBootException("第"+ key+ "行收款方银行代码不能为空");
        }

        if(StringUtils.isBlank(importShippingBillDTO.getCreateTime())){
            throw new JeecgBootException("第"+ key+ "行创建时间不能为空");
        }
        Date createTime = DateUtils.stringToDateTime(importShippingBillDTO.getCreateTime());
        if(createTime == null){
            throw new JeecgBootException("第"+ key+ "行创建时间不正确,应为日期时间文本格式");
        }

        HyShippingNoteBill hyShippingNoteBill = new HyShippingNoteBill();
        hyShippingNoteBill.setBillNum(importShippingBillDTO.getBillNum());
        hyShippingNoteBill.setShippingId(importShippingBillDTO.getShippingId());
        hyShippingNoteBill.setVehicleId(importShippingBillDTO.getVehicleId());
        hyShippingNoteBill.setCarrier(importShippingBillDTO.getCarrier());
        hyShippingNoteBill.setActualCarrierId(importShippingBillDTO.getActualCarrierId());
        hyShippingNoteBill.setVehicleId(importShippingBillDTO.getVehicleId());
        hyShippingNoteBill.setVehicleNumber(importShippingBillDTO.getVehicleNumber());
        hyShippingNoteBill.setVehicleColorCode(importShippingBillDTO.getVehicleColorCode());
        hyShippingNoteBill.setAmt(importShippingBillDTO.getAmt());
        hyShippingNoteBill.setCraccno(importShippingBillDTO.getCraccno());
        hyShippingNoteBill.setBankCode(importShippingBillDTO.getBankCode());
        hyShippingNoteBill.setCreateTime(createTime);
        hyShippingNoteBill.setPayDt(createTime);

        //Added at 2023-07-18 for 增加付款凭证图片
        if (StrUtil.isNotEmpty(importShippingBillDTO.getBankHdImg())) {
            String date = DateUtils.dateToStringNoBar(new Date());
            String serverFolderPath = this.bankPath + File.separator + "paybill" ;
            //支付凭证照片地址
            //String bankHdImg = PhotoCrawlerUtil.downloadAbsolutePathPic(importShippingBillDTO.getBankHdImg(), serverFolderPath, date);
            this.applicationEventPublisher.publishEvent(PicDownloadEvent.builder()
                    .type("bill")
                    .downloadUrl(importShippingBillDTO.getBankHdImg())
                    .serverFolderPath(serverFolderPath)
                    .serverFolderName(date)
                    .build()
            );

            //覆盖导入的长地址，启用网货平台对应的短地址,前面拼接paybill目录
            int lastIndex = importShippingBillDTO.getBankHdImg().lastIndexOf('/');
            String filename = importShippingBillDTO.getBankHdImg().substring(lastIndex);
            String filenameNoSubfix = filename.substring(0, filename.lastIndexOf("."));
            hyShippingNoteBill.setBankHd("paybill/" + date + "/" + filenameNoSubfix + ".pdf");

            log.info("保存支付凭证图片地址, {} {} {}", hyShippingNote.getShippingNoteNumber(), importShippingBillDTO.getBankHdImg(), importShippingBillDTO.getBankHdImg());
        }

        hyShippingNoteBill.setShippingNoteNumber(hyShippingNote.getShippingNoteNumber());
        hyShippingNoteBill.setCompanyId(hyShippingNote.getCompanyId());
        hyShippingNoteBill.setDriverId(hyShippingNote.getDriverId());
        hyShippingNoteBill.setVehicleId(hyShippingNote.getVehicleId());
        hyShippingNoteBill.setOrderId(hyShippingNote.getOrderId());
        hyShippingNoteBill.setPayType(hyShippingNote.getPayType());
        hyShippingNoteBill.setCarrierId(hyShippingNote.getCarrierId());

        hyShippingNoteBill.setPayChannel("1");
        hyShippingNoteBill.setBillType("1");
        hyShippingNoteBill.setBillImportFlag("1");
        hyShippingNoteBill.setRespSource("0");
        hyShippingNoteBill.setRespCode("4");

        return hyShippingNoteBill;
    }

    @Override
    public HyShippingNoteBill getBillByShippingId(String shipping_id) {

        return this.getOne(new QueryWrapper<HyShippingNoteBill>()
                .eq("shipping_id", shipping_id)
                .eq("bill_type", "1")
        );
    }

    @Override
    public HyShippingNoteBill getPreBillByShippingId(String shipping_id) {
        return this.getOne(new QueryWrapper<HyShippingNoteBill>()
                .eq("shipping_id", shipping_id)
                .eq("bill_type", "6")
        );
    }

    @Override
    public HyShippingNoteBill getByBillNumForUpdate(String billNum) {
        return baseMapper.getByBillNumForUpdate(billNum);
    }

    @Override
    public void updateRxtInfoById(String id, String rxtInfo) {
        baseMapper.updateRxtInfoById(id, rxtInfo);
    }
}
